﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ZCConsole.VOBC
{
    class HandleVobc
    {
        public List<UInt16> VOBCNonCom = new List<UInt16>();
        Unpack unPack;
        public TrainInfo trainInfo;
        private uint off;
        private ZC zc;

        public void UnPack(Unpack unPack, ZC zc)
        {
            this.zc = zc;
            this.unPack = unPack;
            trainInfo = new TrainInfo();
            GetRunMode();
            GetTrainID();
            GetNcTrain();
            GetPosition();
            GetDirection();
            GetSpeed();
            GetDoorInfo(zc);

            lock (NonCommunicationTrain.LoseTrain)
            {
                if (NonCommunicationTrain.LoseTrain.Keys.Contains(trainInfo.NIDTrain))
                {
                    CancelNonComTrain(trainInfo);
                }
            }

            int num = VOBCNonCom.IndexOf(trainInfo.NIDTrain);
            if (num == -1)
            {
                VOBCNonCom.Add(trainInfo.NIDTrain);
            }
        }
        public void CancelNonComTrain(TrainInfo trainInfo)
        {
            Device PreNonComTrainHeadPosition;
            Device PreNonComTrainTailPosition;
            lock (VOBC.NonCommunicationTrain.LoseTrain)
            {
                PreNonComTrainHeadPosition = VOBC.NonCommunicationTrain.LoseTrain[trainInfo.NIDTrain].HeadPosition;
                PreNonComTrainTailPosition = VOBC.NonCommunicationTrain.LoseTrain[trainInfo.NIDTrain].TailPosition;
                VOBC.NonCommunicationTrain.LoseTrain.Remove(trainInfo.NIDTrain);
            }
            lock (PreNonComTrainHeadPosition)
            {
                HandlePosition(trainInfo, PreNonComTrainHeadPosition);
            }
            lock (PreNonComTrainTailPosition)
            {
                HandlePosition(trainInfo, PreNonComTrainTailPosition);
            }
        }

        private void HandlePosition(TrainInfo trainInfo, Device position)
        {
            if (position is Section)
            {
                Section section = position as Section;
                section.HasNonComTrain.Remove(trainInfo.NIDTrain);
            }
            else if (position is RailSwitch)
            {
                RailSwitch railSwitch = position as RailSwitch;
                railSwitch.HasNonComTrain.Remove(trainInfo.NIDTrain);

                RailSwitch railSwitchNeedToChange = FindAnotherRailswitch(railSwitch);
                if (railSwitchNeedToChange != null)
                {
                    railSwitchNeedToChange.HasNonComTrain.Remove(trainInfo.NIDTrain);
                }
            }
        }

        public RailSwitch FindAnotherRailswitch(RailSwitch railswitch)
        {
            RailSwitch railNeedToChange = zc.data.Devices.Find((Device element) =>
            {
                if (element is RailSwitch)
                {
                    if ((element as RailSwitch).section.Name == railswitch.section.Name && (element as RailSwitch).Name != railswitch.Name)
                    {
                        return true;
                    }
                }
                return false;
            }) as RailSwitch;
            return railNeedToChange;
        }

        /// <summary>
        /// 获取列车运行模式
        /// </summary>
        private void GetRunMode()
        {
            trainInfo.RunMode = (RunMode)unPack.GetByte();
        }

        /// <summary>
        /// 获取屏蔽门信息
        /// </summary>
        /// <param name="zc"></param>
        private void GetDoorInfo(ZC zc)
        {
            bool shouldDoorOpen = unPack.GetByte() == 1 ? true : false;
            trainInfo.PSDoor = shouldDoorOpen;
            if (trainInfo.HeadPosition is Section)
            {
                if ((trainInfo.HeadPosition as Section).LogicCount == 1)
                {
                    PSDoor psdoor = Load.FindDoor.FindRelayPSDoor(trainInfo.HeadPosition as Section, zc);
                    if (psdoor != null)
                    {
                        psdoor.ShouldOpen = shouldDoorOpen;
                    }
                }
            }
        }

        /// <summary>
        /// 获取列车运行速度
        /// </summary>
        private void GetSpeed()
        {
            unPack.SkipBytes(2);
            trainInfo.Speed = unPack.GetUint16();
        }

        /// <summary>
        /// 获取列车运行方向
        /// </summary>
        private void GetDirection()
        {
            unPack.SkipBytes(1);
            trainInfo.TrainDirection = (TrainDir)unPack.GetByte();
        }

        /// <summary>
        /// 获取列车位置（车头及车尾的所在设备及位置的偏移量）
        /// </summary>
        private void GetPosition()
        {
            unPack.SkipBytes(7);
            SectionOrSwitch sectionOrSwitch = (SectionOrSwitch)unPack.GetByte();
            int DeviceId = unPack.GetByte();
            trainInfo.HeadPosition = FindDevice(sectionOrSwitch, DeviceId);
            trainInfo.HeadOffset = unPack.GetUint32();

            if (trainInfo.HeadOffset != off)        //???
            {
                off = trainInfo.HeadOffset;
                Debug.WriteLine("from atp:" + off);
            }

            sectionOrSwitch = (SectionOrSwitch)unPack.GetByte();
            DeviceId = unPack.GetByte();
            trainInfo.TailPosition = FindDevice(sectionOrSwitch, DeviceId);
            trainInfo.TailOffset = unPack.GetUint32();
        }

        /// <summary>
        /// 根据区段或道岔类型以及设备ID找到对应的设备
        /// </summary>
        /// <param name="sectionOrSwitch"></param>
        /// <param name="DeviceId"></param>
        /// <returns></returns>
        private Device FindDevice(SectionOrSwitch sectionOrSwitch, int DeviceId)
        {
            Device device = zc.data.Devices.Find((Device elements) =>
            {
                if (elements is Device)
                {
                    Device dev = elements as Device;
                    if (sectionOrSwitch == SectionOrSwitch.Section)
                    {
                        if (dev is Section)
                        {
                            if ((dev as Section).Id == DeviceId)
                            {
                                return true;
                            }
                        }
                    }
                    else
                    {
                        if (dev is RailSwitch)
                        {
                            if ((dev as RailSwitch).Id == DeviceId)
                            {
                                return true;
                            }
                        }
                    }
                }
                return false;
            }) as Device;
            return device;
        }

        /// <summary>
        /// 标识列车的各种运行信息
        /// </summary>
        private void GetNcTrain()
        {
            unPack.SkipBytes(2);
            trainInfo.NcTrain = (NCTrain)unPack.GetByte();
        }

        /// <summary>
        /// 列车ID
        /// </summary>
        private void GetTrainID()
        {
            trainInfo.NIDTrain = unPack.GetUint16();
        }
    }
}
